import React, { useState, useEffect, useMemo, useCallback } from "react";
import { Common } from "UtilsCommon";
import { useConnectDataAction } from "UseHooks";
import ListView2 from "./listView2";
import * as styles from "../styles/view.scss";
import Base from './base';
import PropertyItem from "./propertyItem";

window._DataGridView = {};

const pageIndexChange = (pageIndex, isData, pageInfo, property, pageAxis) => {
  isData = isData === undefined ? true : isData;
  if (pageIndex > 1 && pageIndex > pageInfo.pageCount) {
    return;
  }

  if (pageIndex === 1) isData = false;

  pageInfo.pageIndex = pageIndex;
  const { pageSize } = pageInfo;

  requestData(pageAxis, property, { property, pageAxis, pageIndex, pageSize, isData });
};

const refresh = (pageInfo, property, pageAxis, pageIndex) => {
  pageInfo.pageIndex = pageIndex || 1;
  pageIndexChange(pageInfo.pageIndex, false, pageInfo, property, pageAxis);
};

const refresh2 = (id, property, pageAxis, primaryKey, queryData) => {
  let index = -1;
  const { dataList, pageInfo } = queryData;
  for (let i = 0; i < dataList.length; i++) {
    if (Common.isEquals(dataList[i][primaryKey], id)) {
      index = i + 1;
      break;
    }
  }

  if (index > 0) {
    let pageIndex;
    const { pageSize } = pageInfo;
    if (index % pageSize === 0) pageIndex = index / pageSize;
    else pageIndex = Math.floor(index / pageSize) + 1;

    const list = [];
    const preIndex = (pageIndex - 1) * pageSize;
    for (let i = 0; i < preIndex; i++) {
      list.push(dataList[i]);
    }
    queryData.dataList = list;

    refresh(pageInfo, property, pageAxis, pageIndex);
  }
};

const receivesearchQuery = (property, pageAxis) => data => {
  pageAxis.eventActions.dataGridView.receivesearchQuery(data, { property, pageAxis });
};

const receiveexcelExport = (property, pageAxis) => data => {
  pageAxis.eventActions.dataGridView.receiveexcelExport(data, { property, pageAxis });
};

const init = (property, pageAxis) => {
  const pageInfo = { pageSize: property.pageSize || 10, pageIndex: 1, pageCount: 0, pageRecord: 0 };

  const receiveFunctions = {
    receivesearchQuery: receivesearchQuery(property, pageAxis),
    receiveexcelExport: receiveexcelExport(property, pageAxis)
  };

  return { queryData: { dataList: null, pageInfo, groupByInfo: null }, receiveFunctions };
};

const setPageInfo = (pageRecord, queryData) => {
  const { pageInfo } = queryData;
  let pageIndex = pageInfo.pageIndex || 1;
  const pageSize = pageInfo.pageSize;
  let pageCount = 0;
  if (pageRecord === 0) { pageIndex = 1; pageCount = 0; }
  else if (pageRecord <= pageSize) { pageCount = 1; pageIndex = 1; }
  else {
    if (pageRecord % pageSize === 0) pageCount = pageRecord / pageSize;
    else pageCount = Common.getIntValue(pageRecord / pageSize) + 1;
  }

  if (pageIndex > pageCount) pageIndex = pageCount;

  queryData.pageInfo = { pageIndex, pageSize, pageCount, pageRecord };
};

const setColunnDataList = (property, queryData) => {
  if (property.columnCount > 0) {
    if (!queryData.dataList || queryData.dataList.length === 0) {
      queryData.columnDataList = [];
      return;
    }

    const dataList = [];
    const { columnCount } = property;

    for (let i = 0; i < columnCount; i++) {
      dataList.push({ itemList: [] });
    }

    for (let i = 0; i < queryData.dataList.length; i++) {
      const index = i % columnCount;
      dataList[index].itemList.push(queryData.dataList[i]);
    }

    queryData.columnDataList = dataList;
  }
};

const setBindDataList = (property, actionData, actionTypes, queryData, primaryKey) => {
  const { searchQuery } = actionTypes;
  const data = actionData[searchQuery];

  if (data === undefined || data.isReceive) return;

  data.isReceive = true;

  if (Common.isArray(data.dataList)) {
    data.dataList.forEach(d => { d.key = Common.createGuid(); if (!d[primaryKey]) d[primaryKey] = d.key; });
    if (data.groupByInfo) queryData.groupByInfo = data.groupByInfo;
    if (data.pageRecord !== undefined) setPageInfo(data.pageRecord, queryData);
    else if (data.pageInfo) queryData.pageInfo = data.pageInfo;

    if (queryData.pageInfo.pageIndex > 1) {
      const dataList = [];
      let count = 0;
      if (queryData.dataList) {
        queryData.dataList.forEach(d => {
          const item = Common.arrayFirst(data.dataList, f => Common.isEquals(f[primaryKey], d[primaryKey], true));
          if (item == null) dataList.push(d);
          else count++;
        });
      }
      data.dataList.forEach(d => dataList.push(d));
      queryData.pageInfo.pageRecord -= count;
      queryData.dataList = dataList;
    }
    else {
      queryData.dataList = data.dataList;
    }
  }

  setColunnDataList(property, queryData);
};

const setRowData = (properties, rowData, property, pageAxis) => {
  properties.forEach(p => {
    p.id = Common.createGuid();
    p.rowData = rowData;
    if (!Common.isNullOrEmpty(rowData.data[p.name])) {
      p.defaultValue = rowData.data[p.name];
    }
    if (p.linkUrl) {
      p.linkUrl = Common.replaceDataContent(rowData.data, p.linkUrl, true);
    }
    if (p.properties) setRowData(p.properties, rowData, property, pageAxis);
    if (property.expendSetData) pageAxis.getFunction(property.expendSetData)({ property, p, rowData });
  });
};

const renderRowItems = (property, pageId, itemList, index, primaryKey, pageRecord, pageAxis) => {
  return <div key={index} style={property.columnItemStyle}>
    {itemList.map((m, i) => renderRow(property, pageId, m, i, primaryKey, pageRecord, pageAxis))}
  </div>;
};

const renderRow = (property, pageId, data, index, primaryKey, pageRecord, pageAxis) => {
  if (data.isNoData) {
    if (property.properties.length > 2 && !data.isNull) {
      return <PropertyItem key={index} property={property.properties[2]} view={property} pageId={pageId} />;
    }
    return null;
  }
  if (data.itemList) {
    return renderRowItems(property, pageId, data.itemList, index, primaryKey, pageRecord, pageAxis);
  }

  const props = { data, key: data[primaryKey], property, pageId, pageRecord };

  if (property.properties && !data._isDelete) {
    const rowProperties = property.properties.length > 0 ? [property.properties[0]] : property.properties;
    const properties = Common.clone(rowProperties);

    setRowData(properties, props, property, pageAxis);

    return Base.renderProperties2(properties, property, pageId);
  }
  return <div key={index}></div>;
};

const setGroupByPropertiesValue = (property, pageAxis, properties, data) => {
  setRowData(properties, { data }, property, pageAxis);
};

const renderHeader = (property, pageAxis, pageId, itemCount, pageRecord, groupByInfo) => {
  return () => {
    const { pageInfoStyle, pageInfoTextStyle } = property;

    const headerProperty = property.properties.length > 1 ? property.properties[1] : null;
    const groupbyProperty = groupByInfo && property.isGroupByQuery && property.properties.length > 3 ? Common.clone(property.properties[3]) : null;
    if (groupbyProperty) {
      groupbyProperty.id = Common.createGuid();
      setGroupByPropertiesValue(property, pageAxis, groupbyProperty.properties, groupByInfo);
    }
    return (
      <React.Fragment>
        {headerProperty && <PropertyItem property={headerProperty} view={property} pageId={pageId} />}
        {groupbyProperty && pageRecord > 0 && <PropertyItem property={groupbyProperty} view={property} pageId={pageId} />}
        {property.isShowRecord !== false && pageRecord > 0 && <div className="divShowRecord" style={pageInfoStyle}><span style={pageInfoTextStyle}>当前显示：{itemCount}条</span><span style={pageInfoTextStyle}>总记录：{pageRecord}条</span></div>}
      </React.Fragment>
    );
  };
};

//dataList：复杂对象实现数据列表
//queryData：查询数据:数据列表、分页信息、分组信息
const renderDataView = (property, pageId, queryData, primaryKey, actionData, actionTypes, pageIndexChange, pageAxis) => {
  setBindDataList(property, actionData, actionTypes, queryData, primaryKey);
  const { dataList, groupByInfo, columnDataList } = queryData;
  const { pageIndex, pageRecord } = queryData.pageInfo;
  const itemCount = dataList ? dataList.length : 0;
  const hasMore = itemCount < pageRecord;

  let dataList2 = columnDataList || dataList;
  if ((!dataList2 || dataList2.length === 0) && property.isFixHeader) dataList2 = [{ isNoData: true, isNull: !dataList2 }];

  return (<ListView2
    property={property}
    pageIndex={pageIndex}
    dataList={dataList2}
    hasMore={hasMore}
    pageIndexChange={pageIndexChange}
    renderHeader={renderHeader(property, pageAxis, pageId, itemCount, pageRecord, groupByInfo)}
    renderRow={(rowData, index) => renderRow(property, pageId, rowData, index, primaryKey, pageRecord, pageAxis)} />);
};

const setColumnsVisible2 = (visibleColNames, property, pageAxis, pageInfo) => {
  property.columnProperties.forEach(p => { p.isVisible = (visibleColNames.indexOf(p.name) >= 0); });
  if (property.isGroupByQuery) {
    pageInfo.pageIndex = 1;
    refresh(pageInfo, property, pageAxis);
  }
};

const requestData = (pageAxis, property, props) => {
  if (property.eventActionName) pageAxis.invokeEventAction(property.eventActionName, props);
  else if (property.eventAction) pageAxis.invokeEventAction2(property.eventAction, props);
};

let _MinActionType = 9999999;

const getMinActionType = () => {
  _MinActionType += 1;

  return _MinActionType * 100;
};

const getDataActionOptions = (property) => {
  if (property.dataActionOptions) return property.dataActionOptions;
  const minActionType = getMinActionType();
  const actionTypes = {
    //搜索查询
    searchQuery: minActionType,
    //Excel导出
    excelExport: minActionType + 1
  };
  property.dataActionOptions = { name: 'DataGridView_' + minActionType, minActionType, maxActionType: minActionType + 99, actionTypes };
  return property.dataActionOptions;
};

export default React.memo((props) => {
  const { property, pageAxis } = Base.getProps(props);
  const { dispatch, dispatchAction, setActionState } = pageAxis;

  //使用链接数据行为
  const [invokeDataAction, actionTypes, actionData] = useConnectDataAction(dispatch, dispatchAction, setActionState, 'components_dataGridView', getDataActionOptions(property));

  const [isVisible, setIsVisible] = useState(property.isVisible !== false);
  const { primaryKey } = Base.getEntity(property);

  const { queryData, receiveFunctions } = useMemo(() => init(property, pageAxis), [property, pageAxis]);

  useEffect(() => {
    if (property.isSearchQuery !== false) requestData(pageAxis, property, { property, isData: property.isPaging === false, pageSize: property.pageSize, pageAxis });
  }, [property, pageAxis]);

  useEffect(() => {
    pageAxis.receiveActionDataToObject(receiveFunctions, actionTypes, actionData);
  }, [receiveFunctions, pageAxis, property, actionTypes, queryData, actionData]);

  const onPageIndexChange = useCallback((index) => {
    pageIndexChange(index, true, queryData.pageInfo, property, pageAxis);
  }, [queryData, property, pageAxis]);

  property.setIsVisible = (v) => { property.isVisible = v; setIsVisible(v); };
  property.invokeDataAction = invokeDataAction;
  property.actionTypes = actionTypes;
  property.getPageRecord = () => queryData.pageInfo.pageRecord;
  property.refresh = (v) => { if (v) queryData.pageInfo.pageIndex = v; refresh(queryData.pageInfo, property, pageAxis); };
  property.setDataLoading = (l) => { };
  property.getExcelExportProperties = () => property.columnProperties;
  property.setColumnsVisible2 = (visibleColNames) => setColumnsVisible2(visibleColNames, property, pageAxis, queryData.pageInfo);
  property.refresh2 = (id) => refresh2(id, property, pageAxis, primaryKey, queryData);
  pageAxis.onRefreshData = () => {
    return new Promise((resolve) => {
      pageIndexChange(1, false, queryData.pageInfo, property, pageAxis);

      property.setLoadComplete2 = () => {
        resolve();
        property.setLoadComplete2 = null;
      };
    });
  };
  window._DataGridView.refresh = () => pageIndexChange(1, false, queryData.pageInfo, property, pageAxis);

  if (!isVisible) return null;

  const className = Base.getClassName(property, styles);

  return (<div className={className} style={property.style}>
    {renderDataView(property, pageAxis.id, queryData, primaryKey, actionData, actionTypes, onPageIndexChange, pageAxis)}</div>);
});